package com.luo.dt.seata.at.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luo.dt.common.execption.MsgRuntimeException;
import com.luo.dt.common.model.result.RespResult;
import com.luo.dt.seata.at.mapper.AccountMapper;
import com.luo.dt.seata.at.model.dto.DebitDto;
import com.luo.dt.seata.at.model.entity.Account;
import com.luo.dt.seata.at.service.IAccountService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * 用户信息 服务实现类
 *
 * @author luohq
 * @date 2022-12-12
 */
@Service
@Slf4j
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements IAccountService {


    /**
     * 分支事务仅使用普通@Transactional注解即可
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespResult debit(DebitDto debitDto) {
        log.info("开始TCC分支事务，XID={}", RootContext.getXID());
        log.info("用户扣款，参数：{}", debitDto);
        int retCount = this.baseMapper.debit(debitDto.getUserId(), debitDto.getMoney());
        log.info("用户扣款，结果：{}", retCount);
        if (0 >= retCount) {
            throw new MsgRuntimeException("用户扣款失败！");
        }
        return RespResult.success();
    }

    @Override
    public Boolean commitDebit(BusinessActionContext context) {
        log.info("TCC提交成功, XID={}, debitDto={}", context.getXid(), context.getActionContext("debitDto"));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelDebit(BusinessActionContext context) {
        DebitDto debitDto = context.getActionContext("debitDto", DebitDto.class);
        log.warn("TCC回滚业务, XID={}, debitDto={}", context.getXid(), debitDto);
        log.info("用户补款，参数：{}", debitDto);
        int retCount = this.baseMapper.debit(debitDto.getUserId(), debitDto.getMoney().multiply(new BigDecimal(-1)));
        log.info("用户补款，结果：{}", retCount);
        return true;
    }
}
